DynamoDB を触っていて気づいたことメモ(AWS SAM)
https://gyazo.com/af370535c3c0e20e5829c812dc87a20c
はじめに
DynamoDB は NoSQL 型の DB ですが、私は今まで RDB ばかり触ってきたので、正直とても戸惑いました。
(本当は今回も RDS 使いたかったんですが、高かった。。)
色々気づいたことがあったのでメモを残そうと思います。
基本的に SAM を使用して構築していたので、 SAM を使った話になります。 インデックスがよく分からない
インデックスの指定がいまいちよくわかりませんでした。
スキーマレスなので、あらかじめインデックスを決めておかないと、取得やソートがうまくいかないことはなんとなく理解したつもりでいましたが、実際にテーブルを作成する段になって色々混乱しました。
こちらの Qiita の記事を拝見し、ローカルや本番で試してみてやっと掴めてきた感じがあります。
基本的には、パーティションキーとレンジキーをそれぞれ 1 つずつしか設定できないのですが、セカンダリーキーを使用して、 別テーブルを作成すること で、別のレコードから検索ができます。
プログラム側から呼ぶ時には、使用するインデックスを指定しないと、デフォルトのテーブルが使用されてしまいます。
code:golang
result, err := repo.DynamoDBHandler.Query(&dynamodb.QueryInput{
TableName: aws.String("TableName"),
IndexName: aws.String("OtherIndexName"),
KeyConditionExpression: aws.String("name = :name"),
ExpressionAttributeValues: mapstring*dynamodb.AttributeValue{ ":name": {
S: aws.String("hoge"),
},
},
})
ローカル環境
以前ブログに書きましたが、 docker network を合わせる必要がありそうです。
使用するクレデンシャルやリージョンを合わせる
DynamoDB ローカルにテーブルやデータを作成する場合は、クレデンシャルやリージョンを合わせてリクエストする必要がありそうです。
例えば、あるテーブルをリージョン ap-northeast-1 で作成し、別のリクエストで ap-northeast-2 を指定すると、テーブルやデータがなくてエラーになります。
クレデンシャルも同様です。
これはこれで理解できるのですが、例えばちょっとタイポしたリージョン名でも作成できてしまいます。
私が勝手に詰まっていたのは、 ap-northeast-1 で作成したかったのに、間違って ap-north-east-1 で作成したので、長らくデータが見つからないエラーと戦っていました。
ローカルだけ使用するクレデンシャルを直指定する
ローカルの AWS クレデンシャルは適当な値でも良さそうです。
前述したように、ちゃんとクレデンシャルを統一していれば良いようです。
sam のコンテナの環境変数、 AWS_ACCESS_KEY_ID 、 AWS_SECRET_ACCESS_KEY を設定すれば良いですが、コードでもこんな感じで指定できるらしいです。
code:golang
var awsConf *aws.Config
if len(os.Getenv("DYNAMODB_ENDPOINT")) > 0 {
awsConf = &aws.Config{
Credentials: credentials.NewStaticCredentials("hogehoge", "fugafuga", ""),
Region: aws.String("ap-northeast-1"),
Endpoint: aws.String(os.Getenv("DYNAMODB_ENDPOINT")),
}
} else {
awsConf = &aws.Config{
Region: aws.String("ap-northeast-1"),
}
}
dynamoSession, err := session.NewSession(awsConf)
if err != nil {
log.Printf("%s", err.Error())
}
dynamoDbHandler := dynamodb.New(dynamoSession)
ちなみに、Go の DynamoDB のサンプルは、英語ドキュメントの方にはもうあるようです。
データを永続化したい
インメモリな DB なので、コンテナを停止してしまうとデータが消えてしまいます。
こちらの記事に記載されていますが、初期コマンドを上書きすることで、データベースのファイルが作成されるようになります。
code:yaml
dynamodb:
image: amazon/dynamodb-local
command: -jar DynamoDBLocal.jar -dbPath /data
volumes:
- $PWD/data:/data
この時出力されるファイルを見ると、 ACCESS_KEY_ID ごとにファイルが作成されます。
本番反映時
テーブル名を参照する
SAM を使用すると、 SimpleTable を使用することで、簡単に作成できます。
この時作成されるテーブル名には、サフィックスっぽいものがつけられるので、アプリケーションにベタ書きしているとテーブルが見つけられない可能性があります。
環境変数で使い分けるようにした方が良さそうです。
code:yaml
Resources:
MyApiFunction:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
TEST_TABLE_NAME: !Ref TestTable
TestTable:
Type: AWS::Serverless::SimpleTable
セカンダリインデックスを使用する場合
SimpleTable だと、デフォルトのインデックスしか設定できないっぽいので、セカンダリインデックスを設定したい場合は CloudFormation のテンプレートを普通に使った方が良さそうです。
code:yaml
TestTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: "Test"
AttributeDefinitions:
-
AttributeName: "title"
AttributeType: "S"
-
AttributeName: "author"
AttributeType: "S"
KeySchema:
-
AttributeName: "title"
KeyType: "HASH"
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
GlobalSecondaryIndexes:
-
IndexName: "NameIndex"
KeySchema:
-
AttributeName: "name"
KeyType: "HASH"
Projection:
NonKeyAttributes:
- "Published"
ProjectionType: "INCLUDE"
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
さいごに
大した作業ではないのですが、 DynamoDB 関連で 1 週間くらい使った気がします。
もうちょっと運用しながら気づいたことがあればブログを書きたいと思います。
誰かの助けになれば嬉しいです。